
/*========================================================================================
 *                                                                                      *
 *               Copyright(c) 2013-2014, Cha SangWoo, All rights reserved.              *
 *                                                                                      *
 * This file is part of ChaOS.                                                          *
 *                                                                                      *
 * Permission to use, copy, modify, and distribute this software in source and binary   *
 * forms and its documentation for any purpose and without fee is hereby granted,       *
 * provided that the above copyright notice appear in all copies and that both that     *
 * copyright notice and this permission notice appear in supporting documentation.      *
 *                                                                                      *
 * THIS SOFTWARE IS PROVIDED BY THE CHA SANGWOO AND CONTRIBUTORS "AS IS" AND ANY        *
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED            *
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.   *
 * IN NO EVENT SHALL CHA SANGWOO OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,    *
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT         *
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,          *
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF            *
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE      *
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,                    *
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                                   *
 *                                                                                      *
========================================================================================*/

#include "co_core.h"
#include "co_thread.h"

#ifdef __cplusplus
    extern "C" {
    namespace ChaOS {
#endif

//////////////////////////////////////  < BEGIN >  ///////////////////////////////////////

/*======================================================================================*/
/*
    @fn             OBJECT co_thread_create(UINT            stack_size,
                                            THREAD_PROC     entry_point,
                                            UINT            argument)

    @brief          Create a thread.

    @param [in]     object - The size of new thread's stack
    @param [in]     pname - The priority of new thread
    @param [in]     pname - argument for new thread

    @return         Object for thread.

    - HISTORY -
    [V00.00.01] 2014-03-23 [aireat] - Created.
*/
/*======================================================================================*/
OBJECT co_thread_create(UINT            stack_size,     // size of stack
                        THREAD_PROC     entry_point,    // entry point for new thread
                        UINT            argument)       // argument for new thread
{
    THREAD_CB   *pthread;

    // check validation
    CO_ASSERT(stack_size > 0);
    CO_ASSERT(entry_point != NULL);

    // allocate heap memory
    pthread = (THREAD_CB*) co_heap_alloc(sizeof(THREAD_CB));
    CO_ASSERT(pthread != NULL);

    // set object ID
    OBJID_SET(pthread, OBJ_THREAD_ID);

    // setting default
    pthread->stack_point = 0x00;
    pthread->state = CO_THREAD_READY;
    pthread->result = CO_OK_SUCCESS;

    CO_THREAD_INIT(pthread);

    // setup stack
    _port_thread_setup_stack(pthread, entry_point, argument, stack_size);

    // add to ready list
    _core_add_ready_list(pthread);

    return (OBJECT) pthread;
}

/*======================================================================================*/
/*
    @fn             VOID co_thread_set_name(OBJECT object, CHAR *pname)

    @brief          

    @param [in]     object - 
    @param [in]     pname - 

    @return         None.

    - HISTORY -
    [V00.00.01] 2014-03-23 [aireat] - Created.
*/
/*======================================================================================*/
#if (FLAG_USE_THREAD_NAME == CO_ENABLE)
VOID co_thread_set_name(OBJECT object, CHAR *pname)
{
    UINT        i;
    THREAD_CB  *pthread = (THREAD_CB*) object;

    // check object ID
    OBJID_CHECK(pthread, OBJ_THREAD_ID);

    // check parameter
    CO_ASSERT(pname != NULL);

    // copy name
    for (i = 0; i < (NAME_LENGTH-1); i++)
    {
        pthread->name[i] = *pname++;

        if (pname == NULL)
            break;
    }

    // make sure that NULL terminate 
    pthread->name[NAME_LENGTH-1] = 0x00;
}
#endif


/*======================================================================================*/
/*
    @fn             VOID co_thread_sleep(UINT16 milisecond)

    @brief          

    @param [in]     milisecond - 

    @return         None.

    - HISTORY -
    [V00.00.01] 2014-03-23 [aireat] - Created.
*/
/*======================================================================================*/
VOID co_thread_sleep(UINT16 timeout)
{
    CO_ASSERT(timeout != WAIT_FOREVER);

    // Do not preocess in ISR
    if (_g_nested_count == CO_NESTED_COUNT_BASE)
    {
        if (timeout)
        {
            THREAD_CB   *pthread = GET_CURRENT_THREAD();

            ///////////////////
            CO_ENTER_CRITICAL();

            pthread->state = CO_THREAD_WAIT_TIME;
            pthread->wait_time = (UINT16) PORT_GET_TICK_IN_MS(timeout);

            _core_add_block_list(pthread);

            CO_LEAVE_CRITICAL();
            ////////////////////
        }

        PORT_SWITCH_IN_THREAD();
    }
}


//////////////////////////////////////  <  END  >  ///////////////////////////////////////

#ifdef __cplusplus
    } /* namespace ChaOS */
    } /* extern "C" */
#endif

